package de.unidue.langtech.teaching.pp.example;

import java.io.File;
import java.io.IOException;
import java.util.*;

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.apache.uima.UimaContext;
import org.apache.uima.collection.CollectionException;
import org.apache.uima.fit.component.JCasCollectionReader_ImplBase;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.util.Progress;
import org.apache.uima.util.ProgressImpl;
import de.unidue.langtech.teaching.pp.type.BaseTime;
import de.unidue.langtech.teaching.pp.type.TimexEvent;

public class Reader extends JCasCollectionReader_ImplBase {
	public static final String PARAM_INPUT_FILE = "InputFile";
	@ConfigurationParameter(name = PARAM_INPUT_FILE, mandatory = true)
	private File inputFile;
	public String text;
	private Queue<File> files = new LinkedList<File>();
	private int numberOfDocuments = 0;
	public NodeList childNodeList;

	// *initializes the reader

	public void initialize(UimaContext context)
			throws ResourceInitializationException {
		super.initialize(context);
		fileList(inputFile);
	}

	@Override
	public void getNext(JCas jcas) throws IOException, CollectionException {

		File file = files.poll();
		try {
			// source: http://www.rgagnon.com/javadetails/java-0573.html
			// first create xml parsing facilities
			DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			// then parse the xml input file
			Document document = documentBuilder.parse(file);

			document.getDocumentElement().normalize();
			//go into the <text>-tag 
			NodeList nodeList = document.getElementsByTagName("TEXT");
			Node textNode = nodeList.item(0);
			//and get the content of it without tags in it
			String text = textNode.getTextContent();
			//give the document text to the jcas
			jcas.setDocumentText(text);

			// get the <dct> timex tag's value attribute for the dct
			nodeList = document.getDocumentElement()
					.getElementsByTagName("DCT");
			nodeList = ((Element) nodeList.item(0))
					.getElementsByTagName("TIMEX3"); // timex3 tag
			Node baseNode = nodeList.item(0);

			//get the attributes of the <TIMEX3>-tag in the <DCT>-tag
			// source: HeidelTime TempEval-3-Reader
			NamedNodeMap documentTimeNodeMap = baseNode.getAttributes();
			Node basetimeNode = documentTimeNodeMap.getNamedItem("value");
			Node idNode = documentTimeNodeMap.getNamedItem("tid");
			//store the attributes in strings
			String basetime = basetimeNode.getTextContent();
			String baseId = idNode.getTextContent();

			//get the filename
			NodeList fileNameList = document.getElementsByTagName("DOCID");
			Node docIDnode = fileNameList.item(0);
			String fileName = docIDnode.getTextContent();
			System.out.println("____________________________________________________________________________");
			System.out.println("Basetime is " + basetime + ". This basetime belongs to file '" + fileName + "'.");

			//give the stored attributes to the jcas
			BaseTime baseTime = new BaseTime(jcas);
			baseTime.setValue(basetime);
			baseTime.setTimexId(baseId);
			baseTime.setFileName(fileName);
			baseTime.addToIndexes();
			int basetimeYear = 0;
			int basetimeMonth = 0;
			int basetimeDay = 0;

			basetimeYear = Integer.parseInt(basetime.substring(0, 4));
			basetimeMonth = Integer.parseInt(basetime.substring(5, 7));
			basetimeDay = Integer.parseInt(basetime.substring(8, 10));
			
			baseTime.setBasetimeYear(basetimeYear);
			baseTime.setBasetimeMonth(basetimeMonth);
			baseTime.setBasetimeDay(basetimeDay);

			//now get all the <timex>-tags in the <text>-tag...
			int i = 0;
			nodeList = document.getDocumentElement().getElementsByTagName("TEXT");
			nodeList = ((Element) nodeList.item(0)).getElementsByTagName("TIMEX3"); // timex3 tag

			int queue = nodeList.getLength();
			//...by creating a nodeList with all timex events. while the nodeList is not empty, you get the next timex event
			while (queue > 0) {
				Node goldNode = nodeList.item(i);
				// check if there are any timex tags in the document
				if (nodeList.getLength() < 1) {
					System.out.println("No timex tags found.");
				} else {
					//same as basetime: get the attributes of the timex tag
					NamedNodeMap timexNodeMap = goldNode.getAttributes();
					Node timexNode = timexNodeMap.getNamedItem("value");
					Node timexIdNode = timexNodeMap.getNamedItem("tid");
					Node timexModeNode = timexNodeMap.getNamedItem("type");

					NodeList chNodeList = goldNode.getChildNodes();
					Node childNode = chNodeList.item(0);
					//get the expression between <TIMEX3> and </TIMEX3>
					String timeExpression = childNode.getTextContent();

					String goldValue = "";
					String id = "";
					String timexMode = "";

					//store the attributes and the expression in strings
					goldValue = timexNode.getTextContent();
					id = timexIdNode.getTextContent();
					timexMode = timexModeNode.getTextContent();

					//give them to the jcas
					TimexEvent timexEvent = new TimexEvent(jcas);
					timexEvent.setGoldValue(goldValue);
					timexEvent.setTimexId(id);
					timexEvent.setTimexMode(timexMode);
					timexEvent.setTimeExpression(timeExpression);
					timexEvent.addToIndexes();

					//controlling the while-construct
					queue--;
					i++;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean hasNext() throws IOException, CollectionException {
		return !files.isEmpty();
	}

	/*
	 * informs the pipeline about the current progress
	 */
	public Progress[] getProgress() {
		return new Progress[] { new ProgressImpl(files.size(),
				numberOfDocuments, "numberOfDocuments") };
	}

	private void fileList(File newFile) throws ResourceInitializationException {
		// source: HeidelTime
		ArrayList<File> myFiles = new ArrayList<File>();

		// check if the given directory path is valid
		if (!newFile.exists() || !newFile.isDirectory())
			throw new ResourceInitializationException();
		else
			myFiles.addAll(Arrays.asList(newFile.listFiles()));

		// check for existence and readability; add handle to the list
		for (File f : myFiles) {
			if (!f.exists() || !f.isFile() || !f.canRead()) {
				System.out.println("No file found.");
			} else {
				files.add(f);
			}
		}

		numberOfDocuments = files.size();
	}
}